<script lang="ts" setup>
import * as d3 from 'd3'

interface DatumType {
  name: string
  value: number
}
const props = defineProps<{
  data: DatumType[]
}>()
const totalValue = computed(() => {
  return props.data.map(x => x.value).reduce((y, x) => y + x, 0)
})
function percent(val: number) {
  return `${(100 * val / totalValue.value).toFixed(1)}%`
}
const container = ref(null as HTMLElement | null)
function draw() {
  // Specify the chart’s dimensions.
  const width = 300
  const height = width

  // Create the color scale.
  const color = d3.scaleOrdinal()
    .domain(props.data.map(d => d.name))
    .range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), props.data.length).reverse())
  // const color = Common.randomColor
  // const color = d3.scaleOrdinal()
  //   .domain(props.data.map(d => d.name))
  //   .range(d3.schemeSpectral[props.data.length])
  //   .unknown('#ccc')

  // Create the pie layout and arc generator.
  const pie = d3.pie()
    .sort(null)
    .value(d => d.value)

  const arc = d3.arc()
    .innerRadius(0)
    .outerRadius(Math.min(width, height) / 2 - 1)

  const labelRadius = arc.outerRadius()() * 0.8

  // A separate arc generator for labels.
  const arcLabel = d3.arc()
    .innerRadius(labelRadius)
    .outerRadius(labelRadius)

  const arcs = pie(props.data)

  // Create the SVG container.
  const svg = d3.create('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('viewBox', [-width / 2, -height / 2, width, height])
    .attr('style', 'max-width: 100%; height: auto; font: 10px sans-serif;')

  // Add a sector path for each value.
  svg.append('g')
    .attr('stroke', 'white')
    .selectAll()
    .data(arcs)
    .join('path')
    .attr('fill', d => color(d.data.name))
    .attr('d', arc)
    .append('title')
    .text(d => `${d.data.name}: ${d.data.value.toLocaleString('en-US')}`)

  // Create a new arc generator to place a label close to the edge.
  // The label shows the value if there is enough room.
  svg.append('g')
    .attr('text-anchor', 'middle')
    // .attr('fill', 'white')
    .selectAll()
    .data(arcs)
    .join('text')
    .attr('transform', d => `translate(${arcLabel.centroid(d)})`)
    .call(text => text.append('tspan')
      .attr('y', '-0.4em')
      .attr('font-weight', 'bold')
      .text(d => d.data.name))
    .call(text => text.filter(d => (d.endAngle - d.startAngle) > 0.25).append('tspan')
      .attr('x', 0)
      .attr('y', '0.7em')
      // .attr('fill-opacity', 0.7)
      .text(d => percent(d.data.value)))

  return svg.node()
}

watchEffect(() => {
  if (container.value && props.data) {
    container.value.innerHTML = ''
    container.value.appendChild(draw()!)
  }
})
</script>

<template>
  <div ref="container" />
</template>

<style scoped>

</style>
